package com.us.usws.batch.resimp.video;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.iwsh.core.common.GlobalConfig;
import net.iwsh.core.exception.GenericRuntimeException;
import net.iwsh.core.exception.TypeMissmatchException;
import net.iwsh.core.utils.IDGenerator;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.ift.CellProcessor;

import com.us.usws.batch.BatchUtils;
import com.us.usws.batch.resimp.BatchBdao;
import com.us.usws.batch.resimp.ResImpAbstractWorker;
import com.us.usws.batch.resimp.result.FailureCellResult;
import com.us.usws.batch.resimp.result.ResImpResult;
import com.us.usws.biz.ResourceStorageReplacer;
import com.us.usws.common.CommonUtils;
import com.us.usws.common.SiteConstants;
import com.us.usws.model.domain.base.BaseDict;
import com.us.usws.model.domain.channel.Channel;
import com.us.usws.model.domain.video.Video;
import com.us.usws.model.domain.video.VideoFile;
import com.us.usws.support.ext.CacheManager;

public class CSVVideoImpWorker extends ResImpAbstractWorker<CSVVideo> {

	private static Log log = LogFactory.getFactory().getInstance(CSVVideoImpWorker.class);

	private static final String[] headers = new String[] { "name", "fileName", "snpashotName", "playLen", "videoTypes", "tags",
			"description" };

	private Date now = new Date();

	private boolean clean;

	public CSVVideoImpWorker(boolean cleanBeforeInsert) {
		this.clean = cleanBeforeInsert;
	}

	@Override
	public CellProcessor[] getProcessors() {

		final CellProcessor[] processors = new CellProcessor[] { new NotNull(), // name
				new NotNull(), // fileName
				new NotNull(), // snpashotName
				new Optional(), // playLen
				new Optional(), // videoTypes
				new Optional(), // tags
				new Optional() // description
		};

		return processors;
	}

	@Override
	public String[] getHeaders() {
		return headers;
	}

	@Override
	public ResImpResult imp() {
		List<CSVVideo> res = getResults();
		if (res == null) {
			throw new GenericRuntimeException("Please load csv first.");
		}

		//ret
		ResImpResult ret = new ResImpResult();
		ret.setTitle("视频导入");

		//		Set<String> videoTypes = new HashSet<>();
		//		for (CSVVideo each : res) {
		//			String s = each.getVideoTypes();
		//			if (s != null) {
		//				String[] ss = StringUtils.split(s, ';');
		//				for (String a : ss) {
		//					videoTypes.add(a.trim());
		//				}
		//			}
		//		}
		//		//check types
		//		for (String each : videoTypes) {
		//			try {
		//				getVideoType(each);
		//			} catch (Exception e) {
		//				ret.getFailures().add(new FailureCellResult("所有", 0, 0, "发现不存在的视频类型：[" + each + "]."));
		//			}
		//		}

		//check channels
		String entry = GlobalConfig.getString("BatchImport/VideoEntry");

		if (ret.getFailureCnt() > 0) {
			ret.setSummaryMsg("文件校验有错，没有执行导入。");
			return ret;
		}

		//loop 1st, get top channels
		int idx = 0;
		List<Video> lists = new ArrayList<>();
		//links, key=channelUid, value=list of videoUid
		Map<String, List<String>> channelVideoLinks = new HashMap<String, List<String>>();
		StringBuilder importFiles = new StringBuilder("{<br>");
		for (CSVVideo each : res) {
			idx++;
			String name = each.getName();
			String fileName = each.getFileName();
			String snapshot = each.getSnpashotName();
			//log.info("video:" + name + "," + fileName + "," + snapshot);
			if (StringUtils.isBlank(name) || StringUtils.isBlank(fileName) || StringUtils.isBlank(snapshot)) {
				ret.getFailures().add(new FailureCellResult(each.getUploadPath(), idx, 0, "视频名称、视频文件、截图文件均不能为空！"));
				continue;
			}

			String absPath = each.getUploadDir() + "/" + fileName;
			File f = new File(absPath);
			if (!f.exists()) {
				log.debug("Try to seek [" + absPath + "] filed");
				ret.getFailures().add(new FailureCellResult(each.getUploadPath(), idx, 2, "视频文件[" + each.getFileName() + "]并不存在。"));
				continue;
			}

			//get channel info
			String dir = each.getUploadDir();
			dir = StringUtils.replace(dir, "\\", "/");
			String bindedName = dir.substring(entry.length());
			if (bindedName.startsWith("/")) {
				bindedName = bindedName.substring(1);
			}

			//prepare video
			VideoFile vf = genVideoFile(each);
			vf.setFileSize(FileUtils.sizeOf(f));
			Video v = genVideo(each, vf, idx);

			//set channel
			Channel c = CacheManager.getChannelCache().getStuChannelBindedName(bindedName);
			if (c == null) {
				ret.getWarnings().add(new FailureCellResult(each.getUploadPath(), idx, 5, "学生频道：[" + bindedName + "]并存在。"));
				continue;
			}

			if (!channelVideoLinks.containsKey(c.getUid())) {
				List<String> l = new ArrayList<String>();
				channelVideoLinks.put(c.getUid(), l);
			}
			channelVideoLinks.get(c.getUid()).add(v.getUid());

			//check types
			if (each.getVideoTypes() != null && each.getVideoTypes().length() > 0) {
				String[] types = StringUtils.split(each.getVideoTypes(), ";");
				for (String et : types) {
					try {
						Integer typeDsid = getVideoType(et);
						BaseDict d = CacheManager.getDictCache().getBaseDictBySepId(SiteConstants.DICT_DOMAIN_VIDEO_TYPE, typeDsid);
						v.setTypeSid(d.getSepId());
						break;
					} catch (Exception e) {
						ret.getFailures().add(new FailureCellResult(each.getUploadPath(), idx, 5, "视频类型[" + each.getVideoTypes() + "]无效。"));
						continue;
					}
				}
				if (types.length > 1) {
					ret.getWarnings().add(
							new FailureCellResult(each.getUploadPath(), idx, 5, "当前不支持多选视频类型，只选用了：[" + each.getVideoTypes() + "]中的第一项。"));
				}
			}

			lists.add(v);
			importFiles.append("&nbsp;&nbsp;&nbsp;").append(each.getFileName()).append("<br>");

			try {
				//copy files
				String videoFilePathFrom = each.getUploadDir() + "/" + each.getFileName();
				String videoFilePathTo = ResourceStorageReplacer.getVideoFilePath(vf.getUid(), vf.getFileExt());
				File tgt = new File(videoFilePathTo);
				if (tgt.exists()) {
					log.debug("Video file [" + videoFilePathTo + "]  already exists. Skip.");
				} else {
					log.debug("Copy... from [" + videoFilePathFrom + "] to [" + videoFilePathTo + "].");
					FileUtils.copyFile(new File(videoFilePathFrom), tgt);
				}
			} catch (IOException e) {
				ret.getFailures().add(new FailureCellResult(each.getUploadPath(), idx, 2, "视频文件[" + each.getFileName() + "]复制失败。"));
				log.error("Copy file failed.", e);
			}

			try {
				//copy snapshots
				String snapshotFrom = each.getUploadDir() + "/" + each.getSnpashotName();
				String snapshotTo = ResourceStorageReplacer.getVideoFileSnapshotPath(vf.getUid(), vf.getSnapshot());
				File tgt = new File(snapshotTo);
				if (tgt.exists()) {
					log.debug("Snapshot file [" + snapshotTo + "]  already exists. Skip.");
				} else {
					log.debug("Copy... from [" + snapshotFrom + "] to [" + snapshotTo + "].");
					FileUtils.copyFile(new File(snapshotFrom), tgt);
				}
			} catch (IOException e) {
				ret.getFailures().add(new FailureCellResult(each.getUploadPath(), idx, 3, "视频截图[" + each.getFileName() + "]复制失败。"));
				log.error("Copy file failed.", e);
			}

		}
		importFiles.append("}<br>");

		if (ret.getFailureCnt() > 0) {
			ret.setSummaryMsg("文件校验有错，没有执行导入。");
			return ret;
		}

		BatchBdao bdao = new BatchBdao();
		bdao.createVidoes(lists, channelVideoLinks, this.clean);

		ret.setSuccessCnt(lists.size());
		ret.setFilePath("见以下列表");
		ret.setSummaryMsg("成功导入视频文件。");
		ret.setSummaryMsg(importFiles.toString());
		return ret;
	}

	private Video genVideo(CSVVideo each, VideoFile vf, int seqNum) {
		Video ret = new Video();
		String uid = IDGenerator.getInstance().genUID();
		ret.setUid(uid);
		ret.setAuthStatusDsid(4);
		ret.setCreateByUid(BatchUtils.ADMIN_UID);
		ret.setCreateDate(now);
		ret.setDescription(each.getDescription());
		ret.setFileUid(vf.getUid());
		ret.setName(each.getName());
		ret.setSeqNum(seqNum);
		if (each.getTags() != null) {
			ret.setTags(StringUtils.replace(each.getTags(), ";", ","));
		}

		ret.setVideoFile(vf);

		return ret;
	}

	private VideoFile genVideoFile(CSVVideo each) {
		VideoFile ret = new VideoFile();
		String uid = IDGenerator.getInstance().genUID();

		ret.setUid(uid);
		ret.setCreateByUid(BatchUtils.ADMIN_UID);
		ret.setCreateDate(now);

		String fileName = each.getFileName();
		ret.setOrigFileName(fileName);

		String ext = getFileExt(fileName);
		ret.setFileExt(ext);
		ret.setMimeType(CommonUtils.getMimeType(ext));

		ret.setSnapshot(uid + "." + getFileExt(each.getSnpashotName()));

		return ret;

	}

	private String getFileExt(String s) {
		int pos = s.lastIndexOf('.');
		String ext = pos >= 0 ? s.substring(pos + 1) : "";
		return ext;
	}

	private Integer getVideoType(String type) {
		switch (type) {
		case "视频日志":
			return 0;
		case "网友分享":
		case "好友分享":
			return 1;
		case "学习交流":
			return 2;
		case "课程回顾":
			return 3;
		case "校园活动":
		case "校内活动":
			return 4;
		case "公益活动":
			return 5;
		case "娱乐在线":
			return 6;
		case "专家讲坛":
			return 7;
		case "才艺天地":
			return 10;
		case "娱乐天地":
			return 11;
		case "社会实践":
			return 12;
		default:
			throw new TypeMissmatchException("Invalid video type:[" + type + "].");
		}
	}

}
